<template>
	<view class="ResourcePreview" v-if="value" @touchmove.stop.prevent>
		<view class="ResourcePreview-header" :style="[headerStyle]">
			<view class="ResourcePreview-header-left">
				<image :src="closeIcon" @click.passive.stop="closePopup" />
			</view>
			<view class="ResourcePreview-header-center">
				<text>{{ index + 1 }}/{{ list.length }}</text>
			</view>
		</view>

		<view class="ResourcePreview-main">
			<swiper class="swiper" :current-item-id="scrollViewItemId" @change="swiperChange">
				<swiper-item
					class="swiper-item"
					:key="swiperItem.formatId"
					:item-id="swiperItem.formatId"
					v-for="(swiperItem, swiperIndex) in formatList"
				>
					<template v-if="swiperItem.type === 'image'">
						<image mode="widthFix" :src="swiperItem.src" @click.prevent.stop="clickFileCallBack" />
					</template>

					<template v-else>
						<video
							lazy-load
							:src="swiperItem.src"
							:id="swiperItem.videoId"
							play-btn-position="center"
							:enable-progress-gesture="false"
							:poster="swiperItem.previewUrl"
							:autoplay="swiperIndex === index"
							@click.prevent.stop="clickFileCallBack"
							:style="{
								height: swiperItem.height
							}"
						/>
					</template>
				</swiper-item>
			</swiper>
		</view>

		<view class="ResourcePreview-footer" :class="{ isFooter: isFooter }">
			<scroll-view scroll-x="true" class="scroll-view" :scroll-into-view="scrollViewItemId" scroll-anchoring scroll-with-animation>
				<view
					:id="item.formatId"
					:key="item.formatId"
					v-for="(item, index) in formatList"
					class="ResourcePreview-footer-item"
					@click.prevent.stop="clickScrollChange(index)"
					:class="{ active: item.formatId === scrollViewItemId }"
				>
					<image :src="item.previewUrl" lazy-load />
				</view>
			</scroll-view>
		</view>
	</view>
</template>

<script>
import { getSystemInfo, defaultImageUrl } from '@/utils';
import { addMaterialPreview, getVideoPreviewUrl } from '@/api/material';
import { downMaterialUrl } from '@/api/newMaterial';

const {
	platform,
	windowHeight,
	safeArea: { top }
} = getSystemInfo();

const IDPrefix = 'LL_PREVIEW_';
const closeIcon = Object.freeze(`${defaultImageUrl}icon/icon_pic_close.png`);

export default {
	name: 'ResourcePreview',

	props: {
		value: {
			type: Boolean,
			default: false
		},

		index: {
			type: [Number, undefined],
			default: undefined
		},

		list: {
			type: Array,
			default: () => {
				return [];
			}
		},

		srcKey: {
			type: String,
			default: 'tempFilePath'
		},

		frequency: {
			type: Boolean,
			default: false
		},

		remote: {
			type: Boolean,
			default: false
		},

		isSelf: {
			type: Boolean,
			default: false
		},

		requestOtherParams: {
			type: Object,
			default: () => {
				return {};
			}
		},

		isNewMaterial: {
			type: Boolean,
			default: false
		}
	},

	data() {
		return {
			closeIcon,

			isFooter: false,
			materialPreviewList: []
		};
	},

	watch: {
		value(e) {
			const { index, list } = this;

			if (e) {
				const emptyArray = Array.from({ length: list.length }).map(() => undefined);

				this.materialPreviewList = emptyArray;

				this.pauseVideo(index);
				this.addMaterialPreview();
			}
		}
	},

	computed: {
		formatList() {
			const { list, srcKey, materialPreviewList } = this;

			const newList = list.map((item, index) => {
				const { id, type, height = 0, previewUrl } = item;

				const temporaryUrl = materialPreviewList[index]?.url;
				const formatHeight = height > windowHeight ? windowHeight : height;

				return {
					id,
					type,
					previewUrl,
					videoId: `LL_VIDEO_${id}`,
					height: `${formatHeight}px`,
					formatId: `${IDPrefix}${index}`,
					src: temporaryUrl || item[srcKey]
				};
			});

			return newList;
		},

		scrollViewItemId() {
			const { index = 0, formatList } = this;

			return formatList[index]?.formatId || undefined;
		},

		headerStyle() {
			const height = platform === 'ios' ? 44 : 48;

			return {
				top: `${top}px`,
				height: `${height}px`
			};
		}
	},

	methods: {
		closePopup() {
			this.isFooter = false;
			this.$emit('input', false);

			this.materialPreviewList = [];
		},

		swiperChange(e) {
			const { index } = this;
			const {
				detail: { current }
			} = e;

			if (index === current) {
				return;
			}

			this.pauseVideo(index, current);
			this.addMaterialPreview(current);
			this.$emit('changeIndex', current);
		},

		clickScrollChange(clickIndex) {
			const { index } = this;

			if (index === clickIndex) {
				return;
			}

			this.pauseVideo(index, clickIndex);
			this.addMaterialPreview(clickIndex);
			this.$emit('changeIndex', clickIndex);
		},

		addMaterialPreview(index = this.index) {
			const { isSelf, list, remote, frequency, requestOtherParams, materialPreviewList, isNewMaterial } = this;
			const { id = 0, type } = list[index] || {};

			if (materialPreviewList[index]?.url) {
				return;
			}

			frequency && addMaterialPreview({ id });

			if (remote && (isSelf || type === 'video')) {
				const actionUrl = isNewMaterial ? downMaterialUrl : getVideoPreviewUrl;
				const params1 = { materialId: id };
				const params2 = { resourceId: id, ...requestOtherParams };
				actionUrl(isNewMaterial ? params1 : params2).then((res) => {
					const url = isNewMaterial ? res?.data?.url : res?.data || '';

					const singleItem = this.materialPreviewList[index] || {};

					const params = {
						id,
						url,
						type,
						...singleItem
					};

					this.materialPreviewList.splice(index, 1, params);
				});
			}
		},

		pauseVideo(firstIndex, lastIndex = this.index) {
			const { formatList, materialPreviewList } = this;
			const { videoId, type } = formatList[lastIndex];

			if (type !== 'video') {
				return;
			}

			let singleItem = materialPreviewList[firstIndex] || {};

			if (singleItem.videoContext) {
				singleItem.videoContext.pause();
			}

			if (materialPreviewList[lastIndex]?.videoContext) {
				materialPreviewList[lastIndex]?.videoContext.play();
				return;
			}

			const videoContext = uni.createVideoContext(videoId, this);
			const currentIndex = firstIndex === lastIndex ? firstIndex : lastIndex;

			singleItem = materialPreviewList[currentIndex] || {};

			this.materialPreviewList.splice(currentIndex, 1, {
				...singleItem,
				videoContext
			});
		},

		clickFileCallBack() {
			this.isFooter = !this.isFooter;
		}
	}
};
</script>

<style lang="scss" scoped>
@import '@/style/common.scss';

.ResourcePreview {
	position: fixed;
	top: 0;
	left: 0;
	width: 100vw;
	height: 100vh;
	z-index: 999999;
	background: #000;

	&-header {
		position: absolute;
		left: 0;
		right: 0;
		z-index: 999;

		display: flex;
		align-items: center;

		&-left {
			width: 116rpx;
			padding-left: 20rpx;

			image {
				width: 96rpx;
				height: 64rpx;
			}
		}

		&-center {
			flex: 1;
			color: #fff;
			font-size: 32rpx;
			display: flex;
			align-items: center;
			justify-content: center;

			text {
				margin-left: -116rpx;
			}
		}
	}

	&-main {
		.swiper {
			height: 100vh;

			&-item {
				height: 100%;
				position: relative;

				image,
				video {
					position: absolute;
					top: 50%;
					left: 0;
					width: 100%;
					transform: translateY(-50%);
				}
			}
		}
	}

	&-footer {
		position: absolute;
		left: 0;
		right: 0;
		transform: translate3d(0, 0, 0);
		transition: transform 0.3s;
		@include Db_iosPositionBottomDistance();

		height: 140rpx;
		background: #222;

		.scroll-view {
			height: 100%;
			white-space: nowrap;
			box-sizing: border-box;
		}

		&-item {
			margin: 20rpx 4rpx;
			display: inline-block;

			image {
				width: 100rpx;
				height: 100rpx;
				opacity: 0.2;
				border-radius: 8px;
			}

			&:first-child {
				margin-left: 20rpx;
			}

			&:last-child {
				margin-right: 20rpx;
			}

			&.active {
				image {
					opacity: 1;
				}
			}
		}

		&.isFooter {
			transform: translate3d(0, calc(constant(safe-area-inset-bottom) + 160rpx), 0);
			transform: translate3d(0, calc(env(safe-area-inset-bottom) + 160rpx), 0);
		}
	}
}
</style>
